#coding=utf8
import re

from pake.exceptions import CompileError, CommandNotFound
from pake.command import CommandParser, Line, ArgumentParser


class PakefileParser(object):
    def __init__(self, pakefile):
        self.pakefile = pakefile
        self.close_vars = False
        self.global_vars = {}
        self.commands = {}

        self.backlog_signature = None
        self.backlog_body = []

    def handle_line(self, line):
        # 注释
        if re.match(r'^\s*#', line.text):
            return

        # 空行
        if re.match(r'^\s*$', line.text):
            return

        if re.match(r'^\w', line.text):
            # global_vars
            if re.match(r'^\w+\s*=', line.text):
                return self.handle_global_vars(line)
            else: #signature
                return self.handle_signature(line)

        # body
        if re.match(r'^\s+[^\s#]+', line.text):
            return self.handle_body(line)

        raise CompileError(u"无法识别格式 [L:{}]: {}".format(line.lineno, line.text))

    def handle_global_vars(self, line):
        if self.close_vars:
            raise CompileError('全局变量在头部声明 [L:{}]: {}'.format(line.lineno, line.text))
        else:
            k, v = line.text.split('=', 1)
            self.global_vars[k] = v.strip().strip('\'').strip('"')

    def handle_signature(self, line):
        self.close_vars = True

        self.command_finished()

        self.backlog_signature = line

    def handle_body(self, line):
        if self.backlog_signature is None:
            raise CompileError(u'缺少命令声明 [L:{}]: {}'.format(line.lineno, line.text))

        line.text = line.text.strip()
        self.backlog_body.append(line)
    
    def command_finished(self):
        if self.backlog_signature is not None:
            command = CommandParser(self.pakefile, self.backlog_signature, self.backlog_body, self.global_vars).parse()
            if command.name in self.commands:
                raise CompileError(u'命令名称已存在 [L:{}][L:{}]: {}'.format(command.lineno, self.commands[command.name].lineno, command.name))

            self.commands[command.name] = command

            self.backlog_signature = None
            self.backlog_body = []


class Pakefile(object):
    def __init__(self, test):
        self.test = test

        self.commands = {} # {name => command}
        self.global_vars = {}

    def parse(self, fpath):
        parser = PakefileParser(self)

        with open(fpath) as f:
            lineno = 1
            for l in f:
                text = l.strip('\n')
                line = Line(lineno, text)
                parser.handle_line(line)

                lineno += 1
        
        parser.command_finished()

        self.commands = parser.commands
        self.global_vars = parser.global_vars 

    def execute(self, name, extra):
        cli_argument = ArgumentParser(Line(0, extra), self.global_vars).parse_argument()
        self.execute_command(name, cli_argument, None, {})

    def execute_command(self, name, cli_argument, bind_argument, global_vars):
        try:
            command = self.commands[name]
        except KeyError:
            raise CommandNotFound(u'命令不存在: {}'.format(name))

        command.execute(cli_argument, bind_argument, global_vars)

    def dump(self):
        print 'global_vars:'
        for k, v in self.global_vars.items():
            print '\t', k, ':', v

        print 'commands:'
        for command in self.commands.values():
            print '\t', command
